#include "main.h"


// 要求将所有代码写在本文件内
// 必须实现下列函数。可以自行增加别的函数。因为采用由代码实现的自动测试用例，所以没有实现上述函数，会有扣分。
// 请勿修改由老师所提供的main.h文件的内容。
#define STACKINCREMENT 10
// 判断刚扫描到的symbol是否操作符。如果symbol是操作符，返回1，否则返回0。
bool is_operator(char symbol) {
    switch (symbol) {
        case '+':
            return 1;
            break;
        case '-':
            return 1;
            break;
        case '*':
            return 1;
            break;
        case '/':
            return 1;
            break;
        case '(':
            return 1;
            break;
        case ')':
            return 1;
            break;
        case '#':
            return 1;
            break;
        default:
            return 0;

    }
}
// 判断刚扫描到的symbol是否操作数。如果symbol是操作数，返回1，否则返回0。
bool is_operand(char symbol){
    switch (symbol) {
        case '0': return 1;break;
        case '1': return 1;break;
        case '2': return 1;break;
        case '3': return 1;break;
        case '4': return 1;break;
        case '5': return 1;break;
        case '6': return 1;break;
        case '7': return 1;break;
        case '8': return 1;break;
        case '9': return 1;break;
        default:
            return 0;
    }
}

// 初始化名为s的栈，初始化成功，返回0，否则返回1。
int init_stack(Stack * s) {
    (*s) = malloc(sizeof(struct stack));
    int * p = (int*)malloc(STACK_MAX_SIZE*sizeof(int));
    (*s)->base = p;
    if(!(*s)->base)
        exit(0);
    (*s)->top = (*s)->base ;
    (*s)->number_of_elements = STACK_MAX_SIZE;
    return 0;

}

// 入栈。返回值表示是否压栈成功：0，成功；1，不成功。
int push(Stack s, char operator_or_operand) {
    if (s->top - s->base == s->number_of_elements){
        //追加空间
        s->base = (int *)realloc(s->base ,(s->number_of_elements +STACKINCREMENT)*sizeof(int));
        if(!s->base ) return 1;
        s->top = s->base+s->number_of_elements;
        s->number_of_elements += STACKINCREMENT;
    }
    *(s->top)++ = operator_or_operand;
    return 0;
}

// 出栈。返回值表示是否出栈成功：0，成功，1，不成功。
int pop(Stack s, char* p_operator_or_operand) {
    if(s->top==s->base)
        return 1;
    --s->top;
    *p_operator_or_operand= *s->top;
    return 0;
}

// 只返回栈顶元素，通过result变量返回栈顶元素的值。函数返回值用于表示执行状态：0，成功；1，不成功。
int get_top(Stack s, char * result) {
    if(s->top==s->base)  //栈已空
        return 1;
    else
        *result = *(s->top-1);
    return 0;
}

// 处理操作符。operator_on_stack_top表示操作符栈栈顶的操作符，just_scanned_operator表示从表达式里刚刚读取的操作符。返回值表示优先级：
//  -1, operator_on_stack_top 的优先级低于 just_scanned_operator；
//  0，operator_on_stack_top 的优先级等于 just_scanned_operator；
//  1，operator_on_stack_top 的优先级高于 just_scanned_operator。

int compare_operators(char operator_on_stack_top, char just_scanned_operator) {
    switch (operator_on_stack_top) {
        case '+':
            switch (just_scanned_operator) {
                case '+':
                    return 1;
                case '-':
                    return 1;
                case '*':
                    return -1;
                case '/':
                    return -1;
                case '(':
                    return -1;
                case ')':
                    return 1;
                case '#':
                    return 1;
            }
        case '-':
            switch (just_scanned_operator) {
                case '+':
                    return 1;
                case '-':
                    return 1;
                case '*':
                    return -1;
                case '/':
                    return -1;
                case '(':
                    return -1;
                case ')':
                    return 1;
                case '#':
                    return 1;
            }
        case '*':
            switch (just_scanned_operator) {
                case '+':
                    return 1;
                case '-':
                    return 1;
                case '*':
                    return 1;
                case '/':
                    return 1;
                case '(':
                    return -1;
                case ')':
                    return 1;
                case '#':
                    return 1;
            }
        case '/':
            switch (just_scanned_operator) {
                case '+':
                    return 1;
                case '-':
                    return 1;
                case '*':
                    return 1;
                case '/':
                    return 1;
                case '(':
                    return -1;
                case ')':
                    return 1;
                case '#':
                    return 1;
            }
        case '(':
            switch (just_scanned_operator) {
                case '+':
                    return -1;
                case '-':
                    return -1;
                case '*':
                    return -1;
                case '/':
                    return -1;
                case '(':
                    return -1;
                case ')':
                    return 0;
                case '#':
                    return 2;
            }
        case ')':
            switch (just_scanned_operator) {
                case '+':
                    return 1;
                case '-':
                    return 1;
                case '*':
                    return 1;
                case '/':
                    return 1;
                case '(':
                    return 2;
                case ')':
                    return 1;
                case '#':
                    return 1;
            }
        case '#':
            switch (just_scanned_operator) {
                case '+':
                    return -1;
                case '-':
                    return -1;
                case '*':
                    return -1;
                case '/':
                    return -1;
                case '(':
                    return -1;
                case ')':
                    return 2;
                case '#':
                    return 0;
            }
    }
}

// 用于简单计算+，-，*，/，operator表示操作符，left_operand表示左操作数，right_operand表示右操作数，结果通过result返回。函数返回值表示计算状态：0，计算成功；1，不成功。
int caculate(char operator, char left_operand, char right_operand, int * result) {
    int i , j;
    switch (left_operand) {
        case'0': i = 0;
            break;
        case'1': i = 1;
            break;
        case'2': i = 2;
            break;
        case'3': i = 3;
            break;
        case'4': i = 4;
            break;
        case'5': i = 5;
            break;
        case'6': i = 6;
            break;
        case'7': i = 7;
            break;
        case'8': i = 8;
            break;
        case'9': i = 9;
            break;
    }
    switch (right_operand) {
        case'0': j = 0;
            break;
        case'1': j = 1;
            break;
        case'2': j = 2;
            break;
        case'3': j = 3;
            break;
        case'4': j = 4;
            break;
        case'5': j = 5;
            break;
        case'6': j = 6;
            break;
        case'7': j = 7;
            break;
        case'8': j = 8;
            break;
        case'9': j = 9;
            break;
    }

    switch (operator) {
        case '+':
            *result = i + j;
            break;
        case '-':
            *result = i - j;
            break;
        case '*':
            *result = i * j;
            break;
        case '/':
            if (j!=0)
                *result = i / j;
            else{
                printf("除数不能为零！\n");
                exit(0);
            }
            break;
    }
    return 0;
}

// 最主要的函数，用于计算表达式的值，比如#3*(2+6)/4#
// 。返回值表示求值状态：0，合法表达式，成功求值；1，表达式不合法。result变量用于返回计算结果。
int evaluate(char * expression, int * result) {
    Stack OPTR;//运算符栈，字符元素
    Stack OPND;//运算数栈，实数元素
    char left_operand;
    char right_operand;
    init_stack(&OPTR);
    init_stack(&OPND);

    int char_position = 0;
    push(OPTR, expression[char_position]);
    char_position +=1;
    char top;
    char w = expression[char_position];

    while (w != '#' || top != '#') {
        if (is_operand(w)) {
            push(OPND, w);
            char_position += 1;
            w = expression[char_position];
        }
        if (is_operator(w)) {
            char c;
            get_top(OPTR, &c);
            if (compare_operators(c, w) == -1) {//-1
                push(OPTR, w);
                w = expression[++char_position];
            }
            if (compare_operators(c, w) == 1) {//1
                int RESULT;
                char Total;
                pop(OPND, &right_operand);
                printf("right operand: %c\n", right_operand);
                pop(OPND, &left_operand);
                printf("left operand: %c\n", left_operand);
                pop(OPTR, &c);
                printf("operator: %c\n", c);

                caculate(c, left_operand, right_operand, &RESULT);
                //printf("result: %d\n", RESULT);
                Total = RESULT + 48;
                printf("Total: %c\n", Total);
                push(OPND, Total);

            }
            if ((compare_operators(c, w) == 0 && (c == '(')) && (w == ')')) {//0 and other
                pop(OPTR, &c);
                w = expression[++char_position];
            }
        }
        get_top(OPTR, &top);
    }
    get_top(OPND, &top);
    *result = top - 48;
    return *result;
}

// 编写你们组自己使用的测试代码
int main(int argc, char * argv[])
{
    char a[] = "#1+2#";
    int t;
    evaluate(a,&t);
    printf("result：%d\n",t);
    printf("ok");
    return 0;
}
